﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;

using System.Drawing;
using Microsoft.DirectX;

namespace NGE
{
    //[Serializable]
    public class Component
    {
        public event KeyboardEvent OnKeyboardEvent;

        public event MouseEvent OnMouseEvent;

        public event GamepadEvent OnGamepadEvent;

        public event InputerEvent OnInputerEvent;

        protected Game game;
        

        public bool Enable = false;
        public bool Visible = false;
        public bool Controllable = false;

        public void EnableAll()
        {
            Visible = true;
            Controllable = true;
            Enable = true;
        }
        public void DisableAll()
        {
            Visible = false;
            Controllable = false;
            Enable = false;
        }

        public string comName;
        public string Name
        {
            get
            {
                return comName;
            }
        }

        public Component(string com_name, Game game)
        {
            comName = com_name;
            this.game = game;
            OnKeyboardEvent = new KeyboardEvent(OnKeyboardEventCode);
            OnMouseEvent = new MouseEvent(OnMouseEventCode);
            OnGamepadEvent += new GamepadEvent(OnGamepadEventCode);
            OnInputerEvent+=new InputerEvent(OnInputerEventCode);
            EnableAll();
        }

        public virtual void OnGamepadEventCode(object sender, int btn, GamepadState gs)
        {
        }
        public virtual void OnKeyboardEventCode(object sender, int key, KeyboardState ks)
        {
        }
        public virtual void OnMouseEventCode(object sender, int x, int y, MouseState ms)
        {
        }

        public virtual void OnInputerEventCode(object sender, object arg)
        { 
        }

        public void BasicHeartbeat()
        {

            delay();
            shock();
            if (FallOutAlpha)
            {
                fallOutAlpha();
            }
            else
            {
                fallOut();
            }
        }
        public virtual void Heartbeat()
        {
        }
        public virtual void Show()
        {
        }
        internal void NotifyKeyboardEvent(int key, KeyboardState ks)
        {
            if (!game.IsFocused)
            {
                return;
            }
            if (!Controllable)
            {
                return;
            }
            OnKeyboardEvent(null, key, ks);
        }
        internal void NotifyMouseEvent(int x, int y, MouseState ms)
        {
            if (!game.IsFocused)
            {
                return;
            }
            if (!Controllable)
            {
                return;
            }
            OnMouseEvent(null, x, y, ms);
        }
        internal void NotifyGamepadEvent(int sender, int btn, GamepadState gs)
        {
            if (!game.IsFocused)
            {
                return;
            }
            if (!Controllable)
            {
                return;
            }
            OnGamepadEvent(sender, btn, gs);
        }
        internal void NotifyInputerEvent(string text)
        {
            if (!game.IsFocused)
            {
                return;
            }
            OnInputerEvent(null, text);
        }

        #region for delay
        protected DateTime DelayBeginTime;
        protected bool IsDelaying;
        protected double DelayTime;
        bool restore;
        public void Delay(int ms)
        {
            Delay(ms, false);
        }
        public void Delay(int ms, bool restore_switch)
        {
            restore = restore_switch;
            if (IsDelaying)
            {
                DelayTime += ms;
            }
            else
            {
                DelayBeginTime = DateTime.Now;
                Enable = Controllable = false;
                IsDelaying = true;
                DelayTime = ms;
            }
        }
        void delay()
        {
            if (IsDelaying)
            {
                TimeSpan ts = DateTime.Now - DelayBeginTime;
                if (ts.TotalMilliseconds > DelayTime)
                {
                    if (restore)
                    {
                        Enable = Controllable = true;
                    }
                    IsDelaying = false;
                }
            }
        }
        #endregion
        #region for shock
        protected Vector3 Vector3Offset;
        protected Point PointOffset
        {
            get
            {
                return new Point((int)Vector3Offset.X, (int)Vector3Offset.Y);
            }
        }

        DateTime ShockBeginTime;
        double ShockTime = 500;
        int ShockRange = 4;
        bool IsShocking;
        public void ShockScreen(double ms)
        {
            ShockScreen(ms, 2);
        }
        public void ShockScreen(double ms, int range)
        {
            //if (IsShocking)
            //{

            //}
            //else
            {
                ShockBeginTime = DateTime.Now;
                ShockTime = ms;
                ShockRange = range * 2;
                IsShocking = true;
            }
        }
        void shock()
        {
            if (IsShocking)
            {
                Vector3Offset = new Vector3();
                TimeSpan ts = DateTime.Now - ShockBeginTime;
                if (ts.TotalMilliseconds > ShockTime)
                {
                    IsShocking = false;
                }
                else
                {
                    int x = Util.Roll(0, ShockRange);
                    int y = Util.Roll(0, ShockRange);
                    int z = Util.Roll(0, ShockRange);
                    x -= (ShockRange / 2);
                    y -= (ShockRange / 2);
                    z -= (ShockRange / 2);
                    //z *= 10;
                    Vector3Offset.X += x;
                    Vector3Offset.Y += y;
                    //Vector3Offset.Z += z;
                }
            }
        }
        #endregion
        #region for fallout
        public bool FallOutAlpha = false;
        public Color FilterColor = Color.FromArgb(255, Color.White);
        bool IsFallOuting = false;
        DateTime FalloutBegineTime;
        double FalloutTime;
        double fallout_interval;
        bool IsFallin;
        public void FallOutSceen(double ms)
        {
            FalloutBegineTime = DateTime.Now;
            FalloutTime = ms;
            fallout_interval = FalloutTime / 255;
            IsFallOuting = true;
            IsFallin = false;
        }
        public void FallInSceen(double ms)
        {
            FallOutSceen(ms);
            IsFallin = true;
        }
        void fallOut()
        {

            if (IsFallOuting)
            {
                TimeSpan ts = DateTime.Now - FalloutBegineTime;
                if (ts.TotalMilliseconds > FalloutTime)
                {
                    if (IsFallin)
                    {
                        FilterColor = Color.FromArgb(255, 255, 255, 255);
                    }
                    else
                    {
                        FilterColor = Color.FromArgb(255, 0, 0, 0);
                    }
                    IsFallOuting = false;
                }
                else
                {
                    int frame = (int)((ts.TotalMilliseconds / (double)(FalloutTime)) * 255);
                    if (frame < 0)
                    {
                        frame = 255;
                    }
                    if (IsFallin)
                    {
                        FilterColor = Color.FromArgb(255, frame, frame, frame);
                    }
                    else
                    {
                        FilterColor = Color.FromArgb(255, 255 - frame, 255 - frame, 255 - frame);
                    }
                }
            }
        }
        void fallOutAlpha()
        {

            if (IsFallOuting)
            {
                TimeSpan ts = DateTime.Now - FalloutBegineTime;
                if (ts.TotalMilliseconds > FalloutTime)
                {
                    if (IsFallin)
                    {
                        FilterColor = Color.FromArgb(255, 255, 255, 255);
                    }
                    else
                    {
                        FilterColor = Color.FromArgb(0, 0, 0, 0);
                    }
                    IsFallOuting = false;
                }
                else
                {
                    int frame = (int)((ts.TotalMilliseconds / (double)(FalloutTime)) * 255);
                    if (frame < 0)
                    {
                        frame = 255;
                    }
                    if (IsFallin)
                    {
                        FilterColor = Color.FromArgb(frame, frame, frame, frame);
                    }
                    else
                    {
                        FilterColor = Color.FromArgb(255 - frame, 255 - frame, 255 - frame, 255 - frame);
                    }
                }
            }

        }
        #endregion
    }
}
